package com.bsj.power.pls.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.power.common.config.cached.PathAlarmCached;
import com.bsj.power.common.config.cached.PathCached;
import com.bsj.power.common.config.cached.RedisCached;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.constant.AlarmEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.FilePathDetailVO;
import com.bsj.power.common.def.dto.alarmReport.AlarmHandleDTO;
import com.bsj.power.common.def.dto.alarmReport.AlarmReportSearchDTO;
import com.bsj.power.common.def.entity.alarmReport.AlarmReport;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.power.common.def.entity.log.VideoOpLog;
import com.bsj.power.common.def.entity.path.Path;
import com.bsj.power.common.def.vo.KeyValueVO;
import com.bsj.power.common.def.vo.pls.AlarmReportCountVO;
import com.bsj.power.common.def.vo.pls.AlarmReportVO;
import com.bsj.power.common.def.vo.pls.alarm.AlarmDurationVO;
import com.bsj.power.common.def.vo.pls.excel.AlarmReportCountExcelVO;
import com.bsj.power.common.def.vo.pls.excel.AlarmReportExcelVO;
import com.bsj.power.common.def.vo.pls.excel.ComAlarmExcelVO;
import com.bsj.power.common.mapper.AlarmReportMapper;
import com.bsj.power.common.mapper.DeviceMapper;
import com.bsj.power.common.mapper.VideoOpLogMapper;
import com.bsj.power.common.util.DateUtils;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.power.pls.service.AlarmReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.bsj.power.common.util.DateUtils.yearMonthDay;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description AlarmReportServiceImpl
 * @time 2024/4/25 17:29
 */
@Slf4j
@Service
public class AlarmReportServiceImpl implements AlarmReportService {

    /**
     * 围栏报警类型
     */
    private static final List<Integer> alarmTypeList = List.of(NumericalConstants.ONE, NumericalConstants.TWO,
            NumericalConstants.THREE);

    static final Map<Integer, String> pathTypeMap, floorMap;

    static {
        pathTypeMap = Map.of(NumericalConstants.ONE, "关键敏感区域", NumericalConstants.TWO, "防异物区域",
                NumericalConstants.THREE, "受限空间区域", NumericalConstants.FOUR, "风险区域");
        floorMap = Map.of(NumericalConstants.ZERO, "室外", NumericalConstants.ONE, "-9.5m", NumericalConstants.TWO, "0m",
                NumericalConstants.THREE, "7.5m", NumericalConstants.FOUR, "16m", NumericalConstants.FIVE, "23m");
    }

    @Resource
    private AlarmReportMapper alarmReportMapper;

    @Autowired
    private PathAlarmCached pathAlarmCached;

    @Autowired
    private PathCached pathCached;

    @Autowired
    private RedisCached redisCached;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private VideoOpLogMapper videoOpLogMapper;

    /**
     * 报警报表
     *
     * @param alarmReportSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.pls.AlarmReportCountVO>>
     * @author ljx
     * @time 2024/4/25 17:32
     */
    @Override
    public JsonResult<List<AlarmReportCountVO>> pageAlarmReportCount(AlarmReportSearchDTO alarmReportSearchDTO) {
        long total = NumericalConstants.ZERO;
        Map<Integer, String> alarmLevelMap = new HashMap<>();
        List<Integer> alarmTypes = getAlarmTypes(alarmReportSearchDTO, alarmLevelMap);
        if (CollectionUtils.isEmpty(alarmTypes)) {
            return JsonResult.success(new ArrayList<>(), total);
        }
        alarmReportSearchDTO.setAlarmTypes(alarmTypes);
        String pathIds = alarmReportSearchDTO.getPathIds();
        if (StringUtils.isNotBlank(pathIds)) {
            List<Integer> pathIdList = Arrays.stream(pathIds.split(",")).map(Integer::parseInt).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(pathIdList)) {
                alarmReportSearchDTO.setPathIdList(pathIdList);
            }
        }
        total = alarmReportMapper.countAlarmReport(alarmReportSearchDTO);
        if (total == NumericalConstants.ZERO) {
            return JsonResult.success(new ArrayList<>(), total);
        }
        alarmReportSearchDTO.initPageNumber();
        alarmReportSearchDTO.setSearchType(NumericalConstants.ONE);
        List<AlarmReportCountVO> alarmReportCountVOS = alarmReportMapper.pageAlarmReportCount(alarmReportSearchDTO);
        if (!CollectionUtils.isEmpty(alarmReportCountVOS)) {
            List<Path> paths = pathCached.hgetAllPathInfo();
            Map<Integer, Path> pathMap = null;
            if (!CollectionUtils.isEmpty(paths)) {
                pathMap = paths.stream().collect(Collectors.toMap(Path::getPathId, Function.identity()));
            }
            for (AlarmReportCountVO alarmReportCountVO : alarmReportCountVOS) {
                String alarmLevel = "普通报警";
                if (!CollectionUtils.isEmpty(alarmLevelMap)) {
                    String str = alarmLevelMap.get(alarmReportCountVO.getAlarmType());
                    if (StringUtils.isNotBlank(str)) {
                        alarmLevel = str;
                    }
                }
                if (!CollectionUtils.isEmpty(pathMap)) {
                    Path path = pathMap.get(alarmReportCountVO.getPathId());
                    if (path != null) {
                        alarmReportCountVO.setPathType(path.getPathType());
                        alarmReportCountVO.setFloor(path.getFloor());
                        alarmReportCountVO.setBuilding(path.getBuilding());
                    }
                }
                alarmReportCountVO.setAlarmLevel(alarmLevel);
            }
        }
        return JsonResult.success(alarmReportCountVOS, total);
    }

    /**
     * 报警详情
     *
     * @param alarmReportSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.pls.AlarmReportVO>>
     * @author ljx
     * @time 2024/5/13 10:10
     */
    @Override
    public JsonResult<List<AlarmReportVO>> alarmReportDetail(AlarmReportSearchDTO alarmReportSearchDTO) {
        long total = NumericalConstants.ZERO;
        Map<Integer, String> alarmLevelMap = new HashMap<>();
        List<Integer> alarmTypes = getAlarmTypes(alarmReportSearchDTO, alarmLevelMap);
        if (CollectionUtils.isEmpty(alarmTypes)) {
            return JsonResult.success(new ArrayList<>(), total);
        }
        String pathIds = alarmReportSearchDTO.getPathIds();
        if (StringUtils.isNotBlank(pathIds)) {
            List<Integer> pathIdList = Arrays.stream(pathIds.split(",")).map(Integer::parseInt).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(pathIdList)) {
                alarmReportSearchDTO.setPathIdList(pathIdList);
            }
        }
        alarmReportSearchDTO.setAlarmTypes(alarmTypes);
        total = alarmReportMapper.countAlarmReportDetail(alarmReportSearchDTO);
        if (total == NumericalConstants.ZERO) {
            return JsonResult.success(new ArrayList<>(), total);
        }
        alarmReportSearchDTO.setSearchType(NumericalConstants.ONE);
        alarmReportSearchDTO.initPageNumber();
        List<AlarmReportVO> alarmReportVOS = alarmReportMapper.alarmReportDetail(alarmReportSearchDTO);
        long time1;
        long time2;
        long currentTime = System.currentTimeMillis();
        Map<Integer, Device> deviceMap = new HashMap<>();
        for (AlarmReportVO alarmReportVO : alarmReportVOS) {
            time1 = DateUtils.strToDate(alarmReportVO.getBeginTime()).getTime();
            String endTime = alarmReportVO.getEndTime();
            time2 = StringUtils.isBlank(endTime) ? currentTime : DateUtils.strToDate(endTime).getTime();
            alarmReportVO.setDurationTime(DateUtils.getDistanceTimeL(time1, time2));
            String filePath = alarmReportVO.getFilePath();
            if (StringUtils.isNotBlank(filePath)) {
                List<FilePathDetailVO> filePathDetailVOS = new LinkedList<>();
                List<String> filePaths = Arrays.stream(filePath.split(",")).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(filePaths)) {
                    filePaths.forEach(path -> {
                        int end = path.lastIndexOf('/');
                        String sub = path.substring(NumericalConstants.ZERO, end);
                        Integer deviceId = Integer.parseInt(sub.substring(sub.lastIndexOf('/') + NumericalConstants.ONE, end));
                        Device device = deviceMap.get(deviceId);
                        if (device == null) {
                            device = deviceMapper.selectById(deviceId);
                            if (device != null) {
                                deviceMap.put(deviceId, device);
                            }
                        }
                        if (device != null) {
                            filePathDetailVOS.add(new FilePathDetailVO(path, device.getNickName()));
                        }
                    });
                }
                alarmReportVO.setFilePathDetailVOS(filePathDetailVOS);
            }
            // 添加摄像头id集合
            alarmReportVO.setCameraIds(pathCached.smemsPathDevice(alarmReportVO.getPathId()));
            String alarmLevel = "普通报警";
            if (!CollectionUtils.isEmpty(alarmLevelMap)) {
                String str = alarmLevelMap.get(alarmReportVO.getAlarmType());
                if (StringUtils.isNotBlank(str)) {
                    alarmLevel = str;
                }
            }
            alarmReportVO.setAlarmLevel(alarmLevel);
        }
        return JsonResult.success(alarmReportVOS, total);
    }

    /**
     * 报警区域统计
     *
     * @param startTime
     * @param endTime
     * @return java.util.Map<java.lang.String, java.lang.Long>
     * @author ljx
     * @time 2024/5/13 15:51
     */
    @Override
    public Map<String, Long> alarmAreaCount(String startTime, String endTime) throws ParseException {
        ParamCheckUtil.isAnyBlank(startTime, endTime);
        if (DateUtils.compareDate(startTime, endTime)) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR);
        }
        List<KeyValueVO> keyValueVOS = alarmReportMapper.alarmAreaCount(startTime, endTime);
        return keyValueVOS.stream().collect(Collectors.toMap(KeyValueVO::getKeyStr, temp -> Long.parseLong(temp.getStrValue())));
    }

    /**
     * 报警次数趋势
     *
     * @param startTime
     * @param endTime
     * @param type      1单位月 2单位日
     * @return java.util.Map<java.lang.String, java.lang.Long>
     * @author ljx
     * @time 2024/5/13 16:24
     */
    @Override
    public Map<String, Long> alarmTimeCount(String startTime, String endTime, Integer type) throws ParseException {
        ParamCheckUtil.isAnyBlank(startTime, endTime);
        if (DateUtils.compareDate(startTime, endTime)) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR);
        }
        ParamCheckUtil.isNull(type);
        String timeFormat = "%Y-%m";
        int value = DateUtils.getMonthsDifference(startTime, endTime);
        if (type.equals(NumericalConstants.ONE)) {
            if (value > 12) {
                throw new ApiException(JsonResultEnum.TOO_MUCH_MONTH_SPAN);
            }
        } else if (type.equals(NumericalConstants.TWO)) {
            Date startDate = DateUtils.strToDate(yearMonthDay, startTime);
            Date entDate = DateUtils.strToDate(yearMonthDay, endTime);
            value = DateUtils.differentDays(startDate, entDate) + NumericalConstants.ONE;
            if (value > 30) {
                throw new ApiException(JsonResultEnum.TOO_MUCH_DAY_SPAN);
            }
            timeFormat = "%Y-%m-%d";
        } else {
            throw new ApiException(JsonResultEnum.PARAM_ERROR);
        }
        Map<String, Long> resultMap = getDateTimeKey(endTime, type, value);
        startTime = startTime + " 00:00:00";
        endTime = endTime + " 23:59:59";
        AlarmReportSearchDTO alarmReportSearchDTO = new AlarmReportSearchDTO();
        alarmReportSearchDTO.setStartTime(startTime);
        alarmReportSearchDTO.setEndTime(endTime);
        alarmReportSearchDTO.setTimeFormat(timeFormat);
        List<KeyValueVO> keyValueVOS = alarmReportMapper.alarmTimeCount(alarmReportSearchDTO);
        keyValueVOS.forEach(keyValueVO -> {
            resultMap.put(keyValueVO.getKeyStr(), Long.parseLong(keyValueVO.getStrValue()));
        });
        return resultMap;
    }

    /**
     * 按时间统计时长
     *
     * @param startTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    @Override
    public List<AlarmDurationVO> alarmDurationCount(String startTime, String endTime) throws ParseException {
        //只计算进围栏报警
        List<AlarmReport> alarmReports = alarmReportMapper.selectList(Wrappers.<AlarmReport>lambdaQuery()
                .in(AlarmReport::getAlarmType, alarmTypeList).between(AlarmReport::getBeginTime, startTime, endTime));
        if (alarmReports.isEmpty()) {
            return null;
        }
        long currentTime = System.currentTimeMillis();
        List<AlarmDurationVO> data = new ArrayList<>();
        //时间格式化
        alarmReports.stream().forEach(item -> item.setBeginTimeStr(DateUtils.dateToStr(yearMonthDay, item.getBeginTime())));
        //按照格式化后的时间分组，分成每天的报警数据
        Map<String, List<AlarmReport>> timeAlarms = alarmReports.stream().collect(Collectors.groupingBy(AlarmReport::getBeginTimeStr));
        List<String> dateAfter = DateUtils.getDateAfter(startTime, endTime);
        for (int i = dateAfter.size() - 1; i >= 0; i--) {
            String dateStr = dateAfter.get(i);
            List<AlarmReport> reports = timeAlarms.get(dateStr);
            if (reports == null) {
                data.add(AlarmDurationVO.builder().data(dateStr).total(0L).build());
                continue;
            }
            //计算时长
            long count = reports.stream().map(alarmReport -> alarmReport.duration(currentTime)).reduce(0L, Long::sum);
            data.add(AlarmDurationVO.builder().data(dateStr).total(count).build());
        }
        return data;
    }

    /**
     * 获取导出数据
     *
     * @param alarmReportSearchDTO
     * @return java.util.List<com.bsj.power.common.def.vo.pls.excel.AlarmReportCountExcelVO>
     * @author ljx
     * @time 2024/5/14 11:53
     */
    @Override
    public List<AlarmReportCountExcelVO> getExportData(AlarmReportSearchDTO alarmReportSearchDTO) {
        List<AlarmReportCountExcelVO> alarmReportCountExcelVOS = new LinkedList<>();
        Map<Integer, String> alarmLevelMap = new HashMap<>();
        List<Integer> alarmTypes = getAlarmTypes(alarmReportSearchDTO, alarmLevelMap);
        if (CollectionUtils.isEmpty(alarmTypes)) {
            return alarmReportCountExcelVOS;
        }
        alarmReportSearchDTO.setAlarmTypes(alarmTypes);
        String pathIds = alarmReportSearchDTO.getPathIds();
        if (StringUtils.isNotBlank(pathIds)) {
            List<Integer> pathIdList = Arrays.stream(pathIds.split(",")).map(Integer::parseInt).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(pathIdList)) {
                alarmReportSearchDTO.setPathIdList(pathIdList);
            }
        }
        alarmReportSearchDTO.setSearchType(NumericalConstants.TWO);
        List<AlarmReportCountVO> alarmReportCountVOS = alarmReportMapper.pageAlarmReportCount(alarmReportSearchDTO);
        if (!CollectionUtils.isEmpty(alarmReportCountVOS)) {
            List<Path> paths = pathCached.hgetAllPathInfo();
            Map<Integer, Path> pathMap = null;
            if (!CollectionUtils.isEmpty(paths)) {
                pathMap = paths.stream().collect(Collectors.toMap(Path::getPathId, Function.identity()));
            }
            String buildingStr = "#机组";
            for (AlarmReportCountVO alarmReportCountVO : alarmReportCountVOS) {
                AlarmReportCountExcelVO alarmReportCountExcelVO = new AlarmReportCountExcelVO();
                BeanUtils.copyProperties(alarmReportCountVO, alarmReportCountExcelVO);
                alarmReportCountExcelVO.setAlarmType(alarmTypeToStr(alarmReportCountVO.getAlarmType()));
                String alarmLevel = "普通报警";
                if (!CollectionUtils.isEmpty(alarmLevelMap)) {
                    String str = alarmLevelMap.get(alarmReportCountVO.getAlarmType());
                    if (StringUtils.isNotBlank(str)) {
                        alarmLevel = str;
                    }
                }
                alarmReportCountExcelVO.setAlarmLevel(alarmLevel);
                if (!CollectionUtils.isEmpty(pathMap)) {
                    Path path = pathMap.get(alarmReportCountVO.getPathId());
                    if (path != null) {
                        alarmReportCountExcelVO.setPathType(pathTypeMap.get(path.getPathType()));
                        alarmReportCountExcelVO.setFloor(floorMap.get(path.getFloor()));
                        Integer building = path.getBuilding();
                        if (building != null) {
                            alarmReportCountExcelVO.setBuilding(building + buildingStr);
                        }
                    }
                }
                alarmReportCountExcelVOS.add(alarmReportCountExcelVO);
            }
        }
        return alarmReportCountExcelVOS;
    }

    /**
     * 处理报警
     *
     * @param alarmHandleDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/5/23 16:02
     */
    @Override
    @Transactional
    public JsonResult handleAlarm(AlarmHandleDTO alarmHandleDTO) {
        log.info("请求参数{}", alarmHandleDTO);
        Long alarmId = alarmHandleDTO.getAlarmId();
        Integer handleWay = alarmHandleDTO.getHandleWay();
        AlarmReport oldAlarmReport = alarmReportMapper.selectById(alarmId);
        if (oldAlarmReport == null) {
            return JsonResult.fail(JsonResultEnum.ALARM_NOT_EXIST);
        }
        //不属于围栏报警不允许处理
        if (!alarmTypeList.contains(oldAlarmReport.getAlarmType())) {
            return JsonResult.fail(JsonResultEnum.ALARM_NOT_EXIST);
        }
        String deviceName = oldAlarmReport.getDeviceName();
        Integer pathId = oldAlarmReport.getPathId();

        //结束报警
        Date date = new Date();
        AlarmReport alarmReport = new AlarmReport();
        AlarmReport alarmCCached = pathAlarmCached.hgetPathAlarmInfo(deviceName, pathId);
        if (alarmCCached != null && oldAlarmReport.getEndTime() == null) {
            alarmReport.setEndTime(date);
        }
        alarmReport.setAlarmId(alarmId);
        alarmReport.setHandleWay(handleWay);
        alarmReport.setAlarmHandleTime(date);
        alarmReport.setRemark(alarmHandleDTO.getRemark());
        alarmReport.setHandleState(NumericalConstants.TWO);
        alarmReport.setEventDescription(alarmHandleDTO.getEventDescription());
        alarmReport.setResponseMeasures(alarmHandleDTO.getResponseMeasures());
        if (alarmReportMapper.updateById(alarmReport) > NumericalConstants.ZERO) {
            pathAlarmCached.hdelPathAlarmInfo(deviceName, pathId);
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 获取报警详情导出数据
     *
     * @param alarmReportSearchDTO
     * @return java.util.List<com.bsj.power.common.def.vo.pls.excel.AlarmReportExcelVO>
     * @author ljx
     * @time 2024/9/5 12:02
     */
    @Override
    public List<AlarmReportExcelVO> getExportDetail(AlarmReportSearchDTO alarmReportSearchDTO) {
        List<AlarmReportExcelVO> alarmReportExcelVOS = new LinkedList<>();
        Map<Integer, String> alarmLevelMap = new HashMap<>();
        List<Integer> alarmTypes = getAlarmTypes(alarmReportSearchDTO, alarmLevelMap);
        if (CollectionUtils.isEmpty(alarmTypes)) {
            return alarmReportExcelVOS;
        }
        String pathIds = alarmReportSearchDTO.getPathIds();
        if (StringUtils.isNotBlank(pathIds)) {
            List<Integer> pathIdList = Arrays.stream(pathIds.split(",")).map(Integer::parseInt).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(pathIdList)) {
                alarmReportSearchDTO.setPathIdList(pathIdList);
            }
        }
        alarmReportSearchDTO.setAlarmTypes(alarmTypes);
        alarmReportSearchDTO.setSearchType(NumericalConstants.TWO);
        List<AlarmReportVO> alarmReportVOS = alarmReportMapper.alarmReportDetail(alarmReportSearchDTO);
        long currentTime = System.currentTimeMillis();
        if (!CollectionUtils.isEmpty(alarmReportVOS)) {
            alarmReportExcelVOS = alarmReportVOS.stream().map(alarmReportVO -> {
                AlarmReportExcelVO alarmReportExcelVO = new AlarmReportExcelVO();
                BeanUtils.copyProperties(alarmReportVO, alarmReportExcelVO);
                long time1 = DateUtils.strToDate(alarmReportVO.getBeginTime()).getTime();
                String endTime = alarmReportVO.getEndTime();
                long time2 = StringUtils.isBlank(endTime) ? currentTime : DateUtils.strToDate(endTime).getTime();
                alarmReportExcelVO.setDurationTime(DateUtils.getDistanceTimeL(time1, time2));
                alarmReportExcelVO.setAlarmType(alarmTypeToStr(alarmReportVO.getAlarmType()));
                alarmReportExcelVO.setDeviceType(LocationDeviceServiceImpl.deviceTypeToStr(alarmReportVO.getDeviceType()));
                alarmReportExcelVO.setHandleState(alarmReportVO.getHandleState().equals(NumericalConstants.ONE) ? "未处理" : "已处理");
                Integer handleWay = alarmReportVO.getHandleWay();
                if (handleWay != null) {
                    alarmReportExcelVO.setHandleWay(handleWayToStr(handleWay));
                }
                String alarmLevel = "普通报警";
                if (!CollectionUtils.isEmpty(alarmLevelMap)) {
                    String str = alarmLevelMap.get(alarmReportVO.getAlarmType());
                    if (StringUtils.isNotBlank(str)) {
                        alarmLevel = str;
                    }
                }
                alarmReportExcelVO.setAlarmLevel(alarmLevel);
                return alarmReportExcelVO;
            }).collect(Collectors.toList());
        }
        return alarmReportExcelVOS;
    }

    /**
     * 组合报警分页
     *
     * @param alarmReportSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.pls.AlarmReportVO>>
     * @author ljx
     * @time 2024/10/12 9:35
     */
    @Override
    public JsonResult<List<AlarmReportVO>> pageComAlarm(AlarmReportSearchDTO alarmReportSearchDTO) {
        String alarmType = alarmReportSearchDTO.getAlarmType();
        ParamCheckUtil.isBlank(alarmType);
        Integer alarmCode = Integer.parseInt(alarmType);
        if (!alarmCode.equals(NumericalConstants.FIVE)) {
            return JsonResult.fail(JsonResultEnum.PARAM_ERROR);
        }
        IPage<AlarmReport> page = new Page<>(alarmReportSearchDTO.getPageNumber(), alarmReportSearchDTO.getPageSize());
        QueryWrapper<AlarmReport> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AlarmReport::getAlarmType, alarmCode)
                .select(AlarmReport::getAlarmId, AlarmReport::getComAlarmName, AlarmReport::getAlarmType, AlarmReport::getBeginTime, AlarmReport::getEndTime);
        String comAlarmName = alarmReportSearchDTO.getComAlarmName();
        if (StringUtils.isNotBlank(comAlarmName)) {
            queryWrapper.lambda().eq(AlarmReport::getComAlarmName, comAlarmName);
        }
        String startTime = alarmReportSearchDTO.getStartTime();
        String endTime = alarmReportSearchDTO.getEndTime();
        if (!StringUtils.isAllBlank(startTime, endTime)) {
            queryWrapper.lambda().between(AlarmReport::getBeginTime, startTime, endTime);
        }
        List<AlarmReportVO> alarmReportVOS = new ArrayList<>();
        IPage<AlarmReport> iPage = alarmReportMapper.selectPage(page, queryWrapper);
        List<AlarmReport> records = iPage.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            long time1;
            long time2;
            long currentTime = System.currentTimeMillis();
            for (AlarmReport alarmReport : records) {
                AlarmReportVO alarmReportVO = new AlarmReportVO();
                BeanUtils.copyProperties(alarmReport, alarmReportVO);
                Date beginTime = alarmReport.getBeginTime();
                Date endTimeDate = alarmReport.getEndTime();
                alarmReportVO.setBeginTime(DateUtils.dateToStr(beginTime));
                time1 = beginTime.getTime();
                time2 = currentTime;
                if (endTimeDate != null) {
                    alarmReportVO.setEndTime(DateUtils.dateToStr(endTimeDate));
                    time2 = endTimeDate.getTime();
                }
                alarmReportVO.setDurationTime(DateUtils.getDistanceTimeL(time1, time2));
                alarmReportVOS.add(alarmReportVO);
            }
        }
        return JsonResult.success(alarmReportVOS, iPage.getTotal());
    }

    /**
     * 获取组合报警导出信息
     *
     * @param alarmReportSearchDTO
     * @return java.util.List<com.bsj.power.common.def.vo.pls.excel.ComAlarmExcelVO>
     * @author ljx
     * @time 2024/10/12 10:19
     */
    @Override
    public List<ComAlarmExcelVO> getExportComAlarmInfo(AlarmReportSearchDTO alarmReportSearchDTO) {
        QueryWrapper<AlarmReport> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AlarmReport::getAlarmType, NumericalConstants.FIVE)
                .select(AlarmReport::getComAlarmName, AlarmReport::getAlarmType, AlarmReport::getBeginTime, AlarmReport::getEndTime);
        String comAlarmName = alarmReportSearchDTO.getComAlarmName();
        if (StringUtils.isNotBlank(comAlarmName)) {
            queryWrapper.lambda().eq(AlarmReport::getComAlarmName, comAlarmName);
        }
        String startTime = alarmReportSearchDTO.getStartTime();
        String endTime = alarmReportSearchDTO.getEndTime();
        if (!StringUtils.isAllBlank(startTime, endTime)) {
            queryWrapper.lambda().between(AlarmReport::getBeginTime, startTime, endTime);
        }
        List<ComAlarmExcelVO> comAlarmExcelVOS = new LinkedList<>();
        List<AlarmReport> alarmReports = alarmReportMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(alarmReports)) {
            long time1;
            long time2;
            long currentTime = System.currentTimeMillis();
            for (AlarmReport alarmReport : alarmReports) {
                ComAlarmExcelVO comAlarmExcelVO = new ComAlarmExcelVO();
                comAlarmExcelVO.setComAlarmName(alarmReport.getComAlarmName());
                comAlarmExcelVO.setAlarmType("组合报警");
                Date beginTime = alarmReport.getBeginTime();
                Date endTimeDate = alarmReport.getEndTime();
                comAlarmExcelVO.setBeginTime(DateUtils.dateToStr(beginTime));
                time1 = beginTime.getTime();
                time2 = currentTime;
                if (endTimeDate != null) {
                    comAlarmExcelVO.setEndTime(DateUtils.dateToStr(endTimeDate));
                    time2 = endTimeDate.getTime();
                }
                comAlarmExcelVO.setDurationTime(DateUtils.getDistanceTimeL(time1, time2));
                comAlarmExcelVOS.add(comAlarmExcelVO);
            }
        }
        return comAlarmExcelVOS;
    }

    /**
     * 根据设备号查询未结束的报警类型
     *
     * @param deviceName
     * @return java.util.List<java.lang.Integer>
     * @author ljx
     * @time 2024/10/24 11:29
     */
    @Override
    public List<Integer> getAlarmTypeByDeviceName(String deviceName) {
        ParamCheckUtil.isBlank(deviceName);
        List<Integer> result = new LinkedList<>();
        Map<String, String> alarmMap = pathAlarmCached.hgetAllPathAlarmInfo(deviceName);
        if (!CollectionUtils.isEmpty(alarmMap)) {
            result.add(NumericalConstants.ONE);
        }
        //异常停留报警
        if (!CollectionUtils.isEmpty(redisCached.hgetAll(RedisConstant.PATH_REMAIN_ALARM_KEY + deviceName))) {
            result.add(NumericalConstants.THREE);
        }
        return result;
    }

    /**
     * uwb报警列表
     *
     * @param alarmReportSearchDTO
     * @return java.util.List<com.bsj.power.common.def.vo.pls.AlarmReportVO>
     * @author ljx
     * @time 2024/11/1 10:29
     */
    @Override
    public List<AlarmReportVO> listUwbAlarm(AlarmReportSearchDTO alarmReportSearchDTO) {
        String startTime = alarmReportSearchDTO.getStartTime();
        String endTime = alarmReportSearchDTO.getEndTime();
        String deviceName = alarmReportSearchDTO.getDeviceName();
        ParamCheckUtil.isAnyBlank(startTime, endTime, deviceName);
        List<AlarmReportVO> alarmReportVOS = new LinkedList<>();
        List<AlarmReport> alarmReports = alarmReportMapper.selectList(Wrappers.<AlarmReport>lambdaQuery().eq(AlarmReport::getDeviceName, deviceName)
                .between(AlarmReport::getBeginTime, startTime, endTime).in(AlarmReport::getAlarmType, alarmTypeList)
                .select(AlarmReport::getAlarmType, AlarmReport::getBeginTime));
        if (!CollectionUtils.isEmpty(alarmReports)) {
            alarmReportVOS.addAll(alarmReports.stream().map(alarmReport -> {
                AlarmReportVO alarmReportVO = new AlarmReportVO();
                alarmReportVO.setAlarmType(alarmReport.getAlarmType());
                alarmReportVO.setBeginTime(DateUtils.dateToStr(alarmReport.getBeginTime()));
                return alarmReportVO;
            }).collect(Collectors.toList()));
        }
        List<VideoOpLog> videoOpLogs = videoOpLogMapper.selectList(Wrappers.<VideoOpLog>lambdaQuery().eq(VideoOpLog::getOpType, 11)
                .eq(VideoOpLog::getDeviceId,deviceName)
                .between(VideoOpLog::getCreateTime, startTime, endTime).select(VideoOpLog::getOpType, VideoOpLog::getCreateTime));
        if (!CollectionUtils.isEmpty(videoOpLogs)) {
            alarmReportVOS.addAll(videoOpLogs.stream().map(videoOpLog -> {
                AlarmReportVO alarmReportVO = new AlarmReportVO();
                alarmReportVO.setAlarmType(videoOpLog.getOpType());
                alarmReportVO.setBeginTime(DateUtils.dateToStr(videoOpLog.getCreateTime()));
                return alarmReportVO;
            }).collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(alarmReportVOS)) {
            alarmReportVOS = alarmReportVOS.stream().sorted(Comparator.comparing(AlarmReportVO::getBeginTime)).collect(Collectors.toList());
        }
        return alarmReportVOS;
    }

    /**
     * 处理方式转换
     *
     * @param handleWay
     * @return java.lang.String
     * @author ljx
     * @time 2024/9/5 15:33
     */
    private String handleWayToStr(Integer handleWay) {
        String resul = "";
        switch (handleWay) {
            case 1:
                resul = "语音通报提示";
                break;
            case 2:
                resul = "人工现场处理";
                break;
            case 3:
                resul = "其他";
                break;
            default:
                log.info("错误的处理方式{}", handleWay);
                break;
        }
        return resul;
    }

    /**
     * 报警类型转换
     *
     * @param alarmType
     * @return java.lang.String
     * @author ljx
     * @time 2024/5/14 14:22
     */
    private String alarmTypeToStr(Integer alarmType) {
        String resul = "";
        switch (alarmType) {
            case 1:
                resul = "基于定位的越线报警";
                break;
            case 2:
                resul = "出围栏报警";
                break;
            case 3:
                resul = "异常停留报警";
                break;
            default:
                log.info("错误的报警类型{}", alarmType);
                break;
        }
        return resul;
    }

    /**
     * 组装日期时间的key值
     *
     * @param endTime
     * @param type    1单位月 2单位日
     * @param value
     * @return java.util.Map<java.lang.String, java.lang.Long>
     * @author ljx
     * @time 2024/5/13 17:19
     */
    private static Map<String, Long> getDateTimeKey(String endTime, Integer type, Integer value) {
        Map<String, Long> resultMap = new HashMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(yearMonthDay);
        LocalDate localDate = LocalDate.parse(endTime, formatter);
        LocalDate temp;
        String key;
        for (int i = 0; i < value; i++) {
            if (type == 1) {
                temp = localDate.minusMonths(i);
                key = temp.toString().substring(0, 7);
            } else {
                temp = localDate.minusDays(i);
                key = temp.toString().substring(0, 10);
            }
            resultMap.put(key, 0L);
        }
        return new TreeMap<>(resultMap);
    }

    /**
     * 获取报警类型集
     *
     * @param alarmReportSearchDTO
     * @param alarmLevelMap
     * @return java.util.List<java.lang.Integer>
     * @author ljx
     * @time 2024/9/8 21:53
     */
    private List<Integer> getAlarmTypes(AlarmReportSearchDTO alarmReportSearchDTO, Map<Integer, String> alarmLevelMap) {
        String alarmType = alarmReportSearchDTO.getAlarmType();
        List<Integer> alarmTypes = Arrays.stream(alarmType.split(",")).map(Integer::parseInt).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(alarmTypes) || !alarmTypeList.containsAll(alarmTypes)) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR);
        }
        Integer inPathAlarmCode = AlarmEnum.IN_PATH_ALARM.getCode();
        Integer outPathAlarmCode = AlarmEnum.OUT_PATH_ALARM.getCode();
        Integer otherAlarmCode = AlarmEnum.OTHER_ALARM.getCode();
//        Integer callHelpCode = AlarmEnum.CALL_HELP_ALARM.getCode();
        Integer alarmLevel = alarmReportSearchDTO.getAlarmLevel();
        Map<String, String> map = redisCached.hgetAll(RedisConstant.ALARM_LEVEL_KEY);
        if (alarmLevel != null) {
            List<Integer> alarmCodes = new LinkedList<>();
            if (alarmLevel < NumericalConstants.ZERO || alarmLevel > NumericalConstants.TWO) {
                throw new ApiException(JsonResultEnum.PARAM_ERROR);
            }
            if (!CollectionUtils.isEmpty(map)) {
                //普通报警，未设置级别的报警
                if (alarmLevel.equals(NumericalConstants.ZERO)) {
                    //所有设置了级别的报警
                    List<Integer> codeList = map.values().stream().map(str -> {
                        List<Integer> codes = JSONObject.parseObject(str, List.class);
                        return codes;
                    }).flatMap(List::stream).collect(Collectors.toList());
                    if (!codeList.contains(inPathAlarmCode) && alarmTypes.contains(inPathAlarmCode)) {
                        alarmCodes.add(inPathAlarmCode);
                    }
                    if (!codeList.contains(outPathAlarmCode) && alarmTypes.contains(outPathAlarmCode)) {
                        alarmCodes.add(outPathAlarmCode);
                    }
                    if (!codeList.contains(otherAlarmCode) && alarmTypes.contains(otherAlarmCode)) {
                        alarmCodes.add(otherAlarmCode);
                    }
//                    if (!codeList.contains(callHelpCode) && alarmTypes.contains(callHelpCode)) {
//                        alarmCodes.add(callHelpCode);
//                    }
                } else {
                    String codesStr = map.get(alarmLevel.toString());
                    if (StringUtils.isNotBlank(codesStr)) {
                        List<Integer> codes = JSONObject.parseObject(codesStr, List.class);
                        if (codes.contains(inPathAlarmCode) && alarmTypes.contains(inPathAlarmCode)) {
                            alarmCodes.add(inPathAlarmCode);
                        }
                        if (codes.contains(outPathAlarmCode) && alarmTypes.contains(outPathAlarmCode)) {
                            alarmCodes.add(outPathAlarmCode);
                        }
                        if (codes.contains(otherAlarmCode) && alarmTypes.contains(otherAlarmCode)) {
                            alarmCodes.add(otherAlarmCode);
                        }
//                        if (codes.contains(callHelpCode) && alarmTypes.contains(callHelpCode)) {
//                            alarmCodes.add(callHelpCode);
//                        }
                    }
                }
            }
            alarmTypes = alarmCodes;
        }
        if (!CollectionUtils.isEmpty(map)) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                Integer level = Integer.parseInt(entry.getKey());
                List<Integer> codes = JSONObject.parseObject(entry.getValue(), List.class);
                if (codes.contains(inPathAlarmCode)) {
                    alarmLevelMap.put(inPathAlarmCode, alarmLevelToStr(level));
                }
                if (codes.contains(outPathAlarmCode)) {
                    alarmLevelMap.put(outPathAlarmCode, alarmLevelToStr(level));
                }
                if (codes.contains(otherAlarmCode)) {
                    alarmLevelMap.put(otherAlarmCode, alarmLevelToStr(level));
                }
//                if (codes.contains(callHelpCode)) {
//                    alarmLevelMap.put(callHelpCode, alarmLevelToStr(level));
//                }
            }
        }
        return alarmTypes;
    }

    /**
     * 报警级别转换
     *
     * @param level
     * @return java.lang.String
     * @author ljx
     * @time 2024/9/8 23:09
     */
    private String alarmLevelToStr(Integer level) {
        String result = "一级报警";
        if (level.equals(NumericalConstants.TWO)) {
            result = "二级报警";
        }
        return result;
    }

}
